package cluster;

import java.io.*;
import java.util.ArrayList;

public class DBSCAN{
    ArrayList<double[]>dataSet;
    int dim;
    int MinPts=5;
    double eps=5;
    DBSCAN(){
        dataSet=new ArrayList<double[]>();
    }

    //data load dataSet
    public void loadDataSet(String filePath){
        File file=new File(filePath);
        FileReader fr;
        try{
            fr=new FileReader(file);
            BufferedReader bis=new BufferedReader(fr);
            String line=null;
            while((line=bis.readLine())!=null){
                String[]str=line.trim().split(" ");
                double[] data=new double[str.length+1];
                for(int i=0;i<str.length;i++){
                    data[i]=Double.parseDouble(str[i]);
                }
                dataSet.add(data);
            }
            dim=dataSet.get(0).length;
            bis.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public int[] cluster(){
        double []clusterMeans;
        double []next_clusterMeans;
        int cluster=0,parameter=1;
        int []flag=new int[dataSet.size()];
        for (int i = 0; i < dataSet.size(); i++) {
            int count = 0;
            dataSet.get(i)[dim - 1] = 1;
            clusterMeans = dataSet.get(i);
            ArrayList<Integer> dataAdd = new ArrayList<Integer>();
            for (int j = 0; j < dataSet.size(); j++) {
                next_clusterMeans = dataSet.get(j);
                if (i != j) {
                    double distance = getDist(clusterMeans, next_clusterMeans);
                    if (distance <= eps) {
                        dataAdd.add(j);
                        count++;
                    }
                }
            }
            int j;
            for (j = 0; j < dataAdd.size(); j++) {
                if(flag[dataAdd.get(j)]!=0) {
                    parameter=flag[dataAdd.get(j)];
                    break;
                }
            }
            if(j==dataAdd.size()){
                cluster++;
                parameter=cluster;
            }
            if (count >= MinPts) {
                for (j = 0; j < dataAdd.size(); j++) {
                    flag[dataAdd.get(j)] = parameter;
                }
            }
        }
        return flag;
    }

    private double getDist(double[]test,double[]data){
        double sum=0;
        for(int n=0;n<test.length-1;n++){
            sum+=(test[n]-data[n])*(test[n]-data[n]);
        }
        return Math.sqrt(sum);
    }

    public static void main(String args[]){
        DBSCAN dbscan=new DBSCAN();
        dbscan.loadDataSet("/home/tang/data.txt");
        int []flag;
        Integer distinct=1,i,j;
        ArrayList<Integer> data = new ArrayList<Integer>();
        flag=dbscan.cluster();
        data.add(flag[0]);
        for(i=1;i<flag.length;i++){
            if(flag[i]==0){
                continue;
            }
            for(j=0;j<data.size();j++){
                if(flag[i]==data.get(j)){
                    break;
                }
            }
            if(j==data.size()){
                distinct++;
                data.add(flag[i]);
            }
        }
        int []counting=new int[distinct];
        System.out.println("总共有"+distinct+"个簇");
        for(i=0;i<distinct;i++){
            System.out.println("第"+(i+1)+"个簇:");
            for(j=0;j<flag.length;j++) {
                if (data.get(i) == flag[j]){
                    System.out.println(dbscan.dataSet.get(j)[0]+" "+dbscan.dataSet.get(j)[1]+" -->"+(i+1));
                    counting[i]++;
                }
            }
            System.out.println("共"+counting[i]+"个数据");
        }
    }
}
